/*
@2024-02-21：
*/

#include "MephistoCAM.h"

#define PORT            1001
#define LISTEN_QUEUE    16
#define BUFFER_SIZE     1024

time_t arm_sys_time = 0;
struct timeval start;
struct timeval end;

char timestamp0[26]; // 'op' + 23+'\n' = 26
char timestamp1[26]; // 'cl' + 23+'\n' = 26
char timestamp[51];

double time_diff(struct timeval *start, struct timeval *end){
    return (end->tv_sec - start->tv_sec) + 1e-6*(end->tv_usec - start->tv_usec);
}

char log_file[1024];
FILE *fp_log_file;

void *serverForClient(void * arg);

int main( int argc, char *argv[] ) {

    if( argc < 2 ){
        printf("\n*********************************************\n");
        printf("usage: %s logfilename.txt\n", argv[1]);
        printf("*********************************************\n");
        return 0;
    }

    //初始化socket
    int sock_fd = socket(AF_INET,SOCK_STREAM,0);
    int on = 1;                                         // Enable address reuse
    setsockopt( sock_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );

    struct sockaddr_in server_sockaddr;                 // socket service
    struct sockaddr_in client_addr;                     // socket client
    socklen_t sin_size = sizeof(struct sockaddr_in);

    memset( &server_sockaddr, 0, sizeof(server_sockaddr));
    bzero( &client_addr, sizeof(client_addr) );

    server_sockaddr.sin_family      = AF_INET;
    server_sockaddr.sin_port        = htons(PORT);
    server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    ///bind成功返回0出错返回-1
    if( bind(sock_fd, (struct sockaddr *)&server_sockaddr, sizeof(server_sockaddr)) == -1 )
    {
        fprintf(stderr, "[Mephisto_RED_CAM] Failed to bind socket, quit.\n");
        exit(-1);
    }

    ///listen成功返回0出错返回-1
    if( listen( sock_fd, LISTEN_QUEUE ) < -1 )
    {
        fprintf(stderr, "[Mephisto_RED_CAM]  listen function failed.\n");
        exit(-1);
    }

    printf("[Mephisto_RED_CAM] start socket listening Port: %d ...\n", PORT);

    while(1) {

        SockInfo *pinfo = NULL;

        for( i=0; i<sock_max_size; i++ ){
            if( infos[i].fd == -1 ){
                pinfo       = &infos[i];
                // pinfo->mcfg = &MCAM_Config;
                break;
            }
        }

        int cfd = accept( sock_fd, (struct sockaddr *)&client_addr, &sin_size ); //accpet
        
        if( -1 == cfd ) {
            perror("[Mephisto_RED_CAM] socket accept failed! \n");
            fprintf(stdout, "[Mephisto_RED_CAM] continue trying to accept socket connections ...\n");
            continue;
        }

        pinfo->fd   = cfd;
        pinfo->mcfg = &MCAM_Config;

        if( pinfo != NULL ){
            fprintf(stdout, "\n[Mephisto_RED_CAM: main thread] --> SockInfo infos[%2d] is activated\n", i);
            fprintf(stdout, "[Mephisto_RED_CAM: main thread] --> socket fd: %d\n\n", cfd);
        }

        sleep(1);
    }

    close(sock_fd);

    fclose(fp_log_file);

    return 0;
}

void *serverForClient(void *arg) {

    char tag[16];

    int fout_name_is_ready = 0;
    char fout_name[128];

    int exp_t_is_ready = 0;
    double exp_t = -1;

    int img_is_dark = 0;
    //////////////////////////////////////////////////////////

    SockInfo           *pinfo  = (SockInfo*)arg;
    MephistoCAM_Config *mcfg   = pinfo->mcfg;
    
    char recvbuf[BUFFER_SIZE];
    char sendbuf[BUFFER_SIZE];

    int new_fd = pinfo->fd;

    while(1) {
        
        bzero(recvbuf, sizeof(recvbuf));
        bzero(sendbuf, sizeof(sendbuf));

        socklen_t len = recv(new_fd, recvbuf, sizeof(recvbuf), 0);

        if( len > 0 ){
            // fputs(recvbuf,stdout);
            fprintf(stdout, "[command from ICS] %s\n", recvbuf);

            if( strcmp(recvbuf, "exposure") == 0 ){
            }
            else if( strlen(recvbuf) == 10 ){
                fprintf(stdout, "> synchronize SoC linux system time...\n");
                arm_sys_time = atoi(recvbuf);

                struct timeval tv;
                tv.tv_sec = arm_sys_time;//+8*3600;
                tv.tv_usec= 0;
                settimeofday(&tv, NULL);
                time_t t_now = time(NULL);
                fprintf(stdout, "> %s\n", ctime(&t_now));
            }
            else{
                fprintf(stdout,"\n*******************************************\n");
                fprintf(stdout, "(%s): **** unkown command: %s ****\n", __func__, recvbuf);
                fprintf(stdout,"*******************************************\n");
                continue;
            }

        }

        usleep(1000);   // 1ms sleep
    }

    close(pinfo->fd);
    pinfo->fd   = -1;
    pinfo->mcfg = NULL;

    close(new_fd);

    fprintf(stdout,"##> thread: %lu closed.\n", pthread_self());

    // cStatus == 0;   // this thread has finised its job, change cStatus to 0

    return NULL;
}



